/*
 * Rectangle2D.cpp
 *
 *  Created on: 18/06/2013
 *      Author: gonzalo
 */

#include "Rectangle2D.h"

Rectangle2D::Rectangle2D(GLuint program) :
		Figure(program) {

	/*this->vertex_buffer_size = 4;
	 this->index_buffer_size = 4;
	 this->normal_buffer_size = this->vertex_buffer_size;
	 this->tangent_buffer_size = this->normal_buffer_size;

	 this->vertex_buffer = new GLfloat[3 * vertex_buffer_size];
	 this->index_buffer = new GLuint[index_buffer_size];
	 this->normal_buffer = new GLfloat[3 * normal_buffer_size];
	 this->tangent_buffer = new GLfloat[3 * tangent_buffer_size];

	 set_coords3(vertex_buffer, 0, -0.5, 0.5, 0.0);
	 set_coords3(vertex_buffer, 1, 0.5, 0.5, 0.0);
	 set_coords3(vertex_buffer, 2, 0.5, -0.5, 0.0);
	 set_coords3(vertex_buffer, 3, -0.5, -0.5, 0.0);

	 set_coords3(normal_buffer, 0, 0.0, 0.0, 1.0);
	 set_coords3(normal_buffer, 1, 0.0, 0.0, 1.0);
	 set_coords3(normal_buffer, 2, 0.0, 0.0, 1.0);
	 set_coords3(normal_buffer, 3, 0.0, 0.0, 1.0);

	 set_coords3(tangent_buffer, 0, 1.0, 0.0, 0.0);
	 set_coords3(tangent_buffer, 1, 1.0, 0.0, 0.0);
	 set_coords3(tangent_buffer, 2, 1.0, 0.0, 0.0);
	 set_coords3(tangent_buffer, 3, 1.0, 0.0, 0.0);

	 for (uint i = 0; i < 4; i++) {
	 this->index_buffer[i] = i;
	 }

	 this->texture_buffer_size = 2 * 4;
	 this->texture_buffer = new GLfloat[texture_buffer_size];

	 set_coords2(this->texture_buffer, 0, 0.0, 1.0);
	 set_coords2(this->texture_buffer, 1, 1.0, 1.0);
	 set_coords2(this->texture_buffer, 2, 1.0, 0.0);
	 set_coords2(this->texture_buffer, 3, 0.0, 0.0);*/

	DatosVertice datos;
	size = 4;
	vertices = new DatosVertice[size];
	index_size = size;
	indices = new unsigned int[index_size];

	// Cara1
	datos.position = glm::vec3(0.5, -0.5, 0.0);
	datos.normal = glm::vec3(0.0, 0.0, 1.0);
	datos.tangent = glm::vec3(0.0, 1.0, 0.0);
	datos.color = glm::vec3(0.2, 0.8, 0.2);
	datos.texture = glm::vec2(1.0, 1.0);
	vertices[0] = datos;
	datos.position = glm::vec3(0.5, 0.5, 0.0);
	datos.normal = glm::vec3(0.0, 0.0, 1.0);
	datos.tangent = glm::vec3(0.0, 1.0, 0.0);
	datos.color = glm::vec3(0.2, 0.8, 0.2);
	datos.texture = glm::vec2(0.0, 1.0);
	vertices[1] = datos;
	datos.position = glm::vec3(-0.5, 0.5, 0.0);
	datos.normal = glm::vec3(0.0, 0.0, 1.0);
	datos.tangent = glm::vec3(0.0, 1.0, 0.0);
	datos.color = glm::vec3(0.2, 0.8, 0.2);
	datos.texture = glm::vec2(0.0, 0.0);
	vertices[2] = datos;
	datos.position = glm::vec3(-0.5, -0.5, 0.0);
	datos.normal = glm::vec3(0.0, 0.0, 1.0);
	datos.tangent = glm::vec3(0.0, 1.0, 0.0);
	datos.color = glm::vec3(0.2, 0.8, 0.2);
	datos.texture = glm::vec2(1.0, 0.0);
	vertices[3] = datos;

	for (uint i = 0; i < index_size; i++) {
		indices[i] = i;
	}

	glGenBuffers(1, &vertex_buffer_object);
	glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_object);
	glGenBuffers(1, &index_buffer_object);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer_object);

	glBufferData(GL_ARRAY_BUFFER, size * sizeof(DatosVertice), vertices, GL_STATIC_DRAW);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, index_size * sizeof(unsigned int), indices, GL_STATIC_DRAW);

	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
	//this->type = GL_TRIANGLES;
	this->type = GL_QUADS;

}

Rectangle2D::~Rectangle2D() {
	delete this->vertex_buffer;
}

void Rectangle2D::draw(GLuint program, glm::mat4 & world_matrix) {
	glm::mat4 matriz = world_matrix * this->model_matrix;

	GLuint location;
	// Normal Matrix es la inversa transpuesta 3x3 de gl_ModelViewMatrix (ViewMatrix = Camara)
	// Matrix = transformacion de afuera + transformacion del objeto

	calculate_and_bind_normal_matrix(program,matriz);
	bind_model_matrix(program,matriz);

	/*glEnableClientState(GL_VERTEX_ARRAY);
	 glEnableClientState(GL_NORMAL_ARRAY);
	 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	 glEnable(GL_CULL_FACE);



	 bind_tangent_buffer("tangent");

	 glVertexPointer(3, GL_FLOAT, 0, vertex_buffer);
	 glNormalPointer(GL_FLOAT, 0, normal_buffer);
	 glTexCoordPointer(2, GL_FLOAT, 0, texture_buffer);

	 glDrawElements(GL_QUADS, index_buffer_size, GL_UNSIGNED_INT, index_buffer);

	 if (this->show_normals) {
	 draw_normals();
	 }

	 glDisableClientState(GL_VERTEX_ARRAY);
	 glDisableClientState(GL_NORMAL_ARRAY);
	 glDisableClientState(GL_TEXTURE_COORD_ARRAY);*/

	int vertex = glGetAttribLocation(program, "vertex"); //0
	int normal = glGetAttribLocation(program, "normal"); //1
	int tangent = glGetAttribLocation(program, "tangent"); //2
	int color = glGetAttribLocation(program, "color"); //3
	int UV = glGetAttribLocation(program, "UV"); //4

	glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_object);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer_object);

	glEnableVertexAttribArray(vertex);
	glVertexAttribPointer(vertex, 3, GL_FLOAT, GL_FALSE, sizeof(DatosVertice), 0);

	glEnableVertexAttribArray(normal);
	glVertexAttribPointer(normal, 3, GL_FLOAT, GL_FALSE, sizeof(DatosVertice), (void*) (3 * sizeof(float)));

	glEnableVertexAttribArray(tangent);
	glVertexAttribPointer(tangent, 3, GL_FLOAT, GL_FALSE, sizeof(DatosVertice), (void*) (6 * sizeof(float)));

	glEnableVertexAttribArray(color);
	glVertexAttribPointer(color, 3, GL_FLOAT, GL_FALSE, sizeof(DatosVertice), (void*) (9 * sizeof(float)));

	glEnableVertexAttribArray(UV);
	glVertexAttribPointer(UV, 2, GL_FLOAT, GL_FALSE, sizeof(DatosVertice), (void*) (12 * sizeof(float)));

	// TEXTURE2D
	if (with_texture) {

		glActiveTexture(GL_TEXTURE0);
		glBindTexture(GL_TEXTURE_2D, this->texture);
		location = glGetUniformLocation(program, "Texture");
		if (location >= 0) {
			glUniform1i(location, 0);
		}
		location = glGetUniformLocation(program, "with_texture");
		if (location >= 0) {
			glUniform1i(location, 1);
		}
	} else {
		location = glGetUniformLocation(program, "with_texture");
		if (location >= 0) {
			glUniform1i(location, 0);
		}
	}

	glDrawElements(this->type, index_size, GL_UNSIGNED_INT, 0);

	glDisableVertexAttribArray(vertex);
	glDisableVertexAttribArray(normal);
	glDisableVertexAttribArray(tangent);
	glDisableVertexAttribArray(color);
	glDisableVertexAttribArray(UV);

	if (with_texture) {
		glBindTexture(GL_TEXTURE_2D, 0);
	}

	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}

void Rectangle2D::set_color(const glm::vec3 & color) {
	glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_object);

	this->vertices = (DatosVertice *) glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);

	for (uint i = 0; i < size; i++) {
		this->vertices[i].color = color;
	}

	glUnmapBuffer(GL_ARRAY_BUFFER);

	glBindBuffer(GL_ARRAY_BUFFER, 0);
}

void Rectangle2D::change_texture_data(const std::vector<DatosVertice> & datos_texturas) {
	glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_object);

	this->vertices = (DatosVertice *) glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);

	for (uint i = 0; i < datos_texturas.size(); i++) {
		this->vertices[i].texture = datos_texturas[i].texture;
	}

	glUnmapBuffer(GL_ARRAY_BUFFER);

	glBindBuffer(GL_ARRAY_BUFFER, 0);
}
